use std::collections::HashSet;

/// [Prime permutations](https://projecteuler.net/problem=49)
fn main() {
    let prime_list = get_prime_list(4);
    let mut hashset = HashSet::new();
    for x in prime_list.iter() {
        hashset.insert(x);
    }
    let len = prime_list.len();
    let max = prime_list[len - 1];
    for i in 0..len {
        let a = prime_list[i];
        for j in (i + 1)..len {
            let b = prime_list[j];
            let c = b * 2 - a;
            if c <= max && hashset.get(&c) == None && basis_eq(a, b, c) {
                println!("{},{},{}", a, b, c);
            }
        }
    }
}

fn get_prime_list(n: u32) -> Vec<usize> {
    if n == 0 {
        return vec![];
    }
    let max = 10_usize.pow(n) - 1;
    let mut buf = vec![true; max];
    buf[0] = false;
    for i in 0..max {
        if buf[i] {
            let j = i + 1;
            let len = max / (i + 1);
            for k in j..=len {
                buf[j * k - 1] = false;
            }
        }
    }
    let min = 10_usize.pow(n - 1) - 1;
    buf[min..]
        .iter()
        .enumerate()
        .filter(|(_, &b)| b)
        .map(|(i, _)| i + min + 1)
        .collect()
}

fn basis_eq(a: usize, b: usize, c: usize) -> bool {
    let get_basis = |n: usize| {
        let mut n = n;
        let mut m = 0;
        while n > 0 {
            m += 2_usize.pow((n % 10) as u32);
            n = n / 10;
        }
        m
    };
    let a = get_basis(a);
    let b = get_basis(b);
    let c = get_basis(c);
    if a == b && a == c {
        true
    } else {
        false
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn is_work() {
        assert_eq!(get_prime_list(1), vec![2, 3, 5, 7]);
        assert_eq!(
            get_prime_list(2),
            vec![11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
        );
    }
}
